
#include "Drop.h"
#include "Common/Item/ItemMgr.h"
#include "DropMgr.h"
#include "Character/Player.h"
#include "ProtoBuffer/AllProtocol.h"
#include "Common/TableData/ItemItemCfg.h"
#include "base/core/Profiler.h"
#include "Character/CreatureMgr.h"
#include "PlaneMgr/PlaneMgr.h"
Drop::Drop() :Creature(), 
		m_pItem(nullptr), 
		m_nGold(0),
		m_byDropType((int8_t)EDropType::EDropType_none)
{
	m_creatureKind = CREATURE_DROP;
	m_nDropTime = g_GetGlobalServerTime()->Tick();
	m_nDropSec = g_GetGlobalServerTime()->UnixSec();
	m_delTick = 0;
	m_nInitProtect = 0;
	m_del = false;
	m_itemSubType = (int32_t)EItemSubType::EItemSubType_none;
	m_fromWho = 0;
	m_setTypeVal.clear();
}

Drop::~Drop()
{
}

bool Drop::Init()
{
	return true;
}

bool Drop::UnInit()
{
	g_GetTimerAxis()->KillAllTimer(this);
	if (nullptr != m_pItem)
	{
		g_GetItemMgr()->FreeItemObj(m_pItem);
		m_pItem = nullptr;
	}	
	m_byDropType = (int8_t)EDropType::EDropType_none;
	m_nDropTime = 0;
	m_nGold = 0;
	m_nInitProtect = 0;
	m_itemSubType = (int32_t)EItemSubType::EItemSubType_none;
	m_fromWho = 0;
	m_setTypeVal.clear();
	if (!m_del)
	{
		m_del = true;
		m_delTick = g_GetGlobalServerTime()->Tick();
	}
	Creature::UnInit();
	return true;
}

bool Drop::Born(uint64_t nDropCid, uint32_t sceneId, Point3<float>& bornPos, int8_t byDropType, SET_UINT64 &setTypeVal, CItemBase *pItem, uint32_t nGolds, int32_t dropInitProtect, SDropSourcePram &sourceParam, uint64_t fromWho /*= 0*/)
{
	if (nullptr == pItem && 0 == nGolds)
	{
		return false;
	}
	if (nullptr != pItem)
	{
		m_pItem = pItem;
		const ItemItemCfgInfo *pItemCfg = g_GetItemItemCfgTable()->GetItemItemCfgInfo(pItem->GetItemID());
		if (nullptr != pItemCfg)
		{
			m_itemSubType = pItemCfg->subType;
		}
	}
	else
	{
		m_nGold = nGolds;
	}
	m_Cid = nDropCid;
	m_byDropType = byDropType;
	m_setTypeVal = setTypeVal;
	m_fromWho = fromWho;
	m_nInitProtect = dropInitProtect;
	bool ret = false;
	BEGIN_PROFILE("Drop EnterScene");
	STransParam transParam;
	transParam.transType = ETransType_Born;
	ret = EnterScene(sceneId, bornPos, transParam);
	END_PROFILE();
	if (!ret)
	{
		m_Cid = 0;
		m_pItem = nullptr;
		m_byDropType = (int8_t)EDropType::EDropType_none;
		m_setTypeVal.clear();
		m_nDropTime = 0;
		m_nInitProtect = 0;
		m_nGold = 0;
		m_itemSubType = (int32_t)EItemSubType::EItemSubType_none;
		m_fromWho = 0;
		return false;
	}

	m_source = sourceParam;
	//如果掉落物怪有位面，则这个掉落物也要设置位面
	Scene *pScene = g_GetSceneMgr()->GetScene(sceneId);
	if (pScene)
	{
		SET_UINT64::iterator iter = m_setTypeVal.begin();
		for (; iter != m_setTypeVal.end(); ++iter)
		{
			uint64_t creatureCid = (*iter);
			Creature * pCreature = pScene->GetCreature(creatureCid);
			if (pCreature)
			{
				g_GetPlaneMgr()->AddCreature(pCreature->GetPlaneID(), m_Cid);
				break; //只需要加入一次
			}
		}		
	}



	if (nullptr != m_pItem && (IsKillStone() || IsCurseFall() || IsCampFlag()))
	{
		DropItemEvent eventParam;
		eventParam.itemId = m_pItem->GetItemID();	
		eventParam.droperType = (CreatureType)CreatureKind();
		eventParam.mapId = GetMapId();
		eventParam.dropPos = GetPos();
		eventParam.dropId = GetCid();
		eventParam.droperId = m_fromWho;
		g_GetEvent()->FireExecute(EVENT_ITEM_DORP, GetCid(), CreatureKind(), &eventParam, sizeof(eventParam));	
	}

	//设置定时器 //因为间隔是一秒一次，这里生存时间是秒为单位，所以定时器次数就是生存时间的秒数
	g_GetTimerAxis()->SetTimer(ETimer_ID_Drop, 1 * 1000, this);

	return true;
}

void Drop::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_ID_Drop:
		{
			DropUpdate(g_GetGlobalServerTime()->Tick());
		}
		break;
	}
}

uint64_t Drop::delTick()
{
	return m_delTick;
}

void Drop::Update(uint64_t tick)
{
	Creature::Update(tick);
}

void Drop::OnDead(uint64_t killerCid)
{
}

bool Drop::ViewFliter(Creature* pCreature, float dict)
{
	if (CREATURE_PLAYER == pCreature->CreatureKind())
	{
		return (!PlayerCanSeen(pCreature->GetCid()));
	}
	return Creature::ViewFliter(pCreature, dict);
}


bool Drop::PlayerCanSeen(CharIDType charId)
{
	if (m_del)
	{
		return false;
	}
	if ((int32_t)EDropType::EDropType_Independence ==  m_byDropType)
	{
		SET_UINT64::iterator iter = m_setTypeVal.find(charId);
		if (iter == m_setTypeVal.end()) //独立掉落不是自己，看不到
		{
			return false;
		}
	}

	return true;
}

void Drop::GetVisibleDataToClient(CreaturesCreateData& cvData)
{
	if (!m_del) //不是待删除状态
	{
		GetDropVisibleData(cvData);
	}	
}

void Drop::GetDropVisibleData(CreaturesCreateData& cvData)
{
	CreaturesCreateData::Drop *pDropData = cvData.add_drops();
	pDropData->set_dropcid(m_Cid);
	pDropData->set_posx(m_pos.x);
	pDropData->set_posy(m_pos.y);
	pDropData->set_posz(m_pos.z);
	pDropData->set_droptype((int32_t)m_byDropType);
	pDropData->set_droptime(m_nDropSec);
	pDropData->set_init_protect(m_nInitProtect);
	if (nullptr != m_pItem)
	{
		ItemProtoInfo *protoItem = pDropData->mutable_item();
		if (nullptr != protoItem)
		{
			g_GetItemMgr()->SetItemProtoInfo(m_pItem, protoItem);
		}
	}
	else
	{
		pDropData->set_gold(m_nGold);
	}

	SET_UINT64::iterator iterVal = m_setTypeVal.begin();
	for (; iterVal != m_setTypeVal.end(); ++iterVal)
	{
		pDropData->add_typeval_lst((*iterVal));
	}

	//LogDebugFmtPrint("[logic] Drop::GetDropVisibleData...dropcid:%llu type:%d ", m_Cid,m_byDropType);
}

void Drop::FindCreatureInScene(Uint64Lst& clist)
{
	/*//根据提供的坐标位置，找对应场景里的生物
	Scene *pScene = g_GetSceneMgr()->GetScene(m_sceneId);
	if (!pScene)
		return;

	uint32_t monsterId = GetLinkMonsterId();

	const MonsterMonsterCfgInfo *pMonsterInfo = g_GetMonsterMonsterCfgTable()->GetMonsterMonsterCfgInfo(monsterId);

	if (pMonsterInfo == nullptr)
	{
		Creature::FindCreatureInScene(clist, srcPos, flength);
	}
	else
	{
		if (pMonsterInfo->viewType == ENUM_MONSTER_VIEW_TYPE_CIRCLE)
		{
			pScene->FindCreatureInCircle(clist, m_pos, m_sightRange);
		}
		else if (pMonsterInfo->viewType == ENUM_MONSTER_VIEW_TYPE_SECTOR)
		{
			//pScene->FindCreatureInSector(clist, m_pos, m_viewAngle, m_sightRange);
		}
		else if (pMonsterInfo->viewType == ENUM_MONSTER_VIEW_TYPE_BALL)
		{
			pScene->FindCreatureInBall(clist, m_pos, m_sightRange);
		}
	}*/
}
//获取剩余时间
uint64_t Drop::GetLeftTime()
{
	uint64_t tick = g_GetGlobalServerTime()->Tick();
	return GetLeftTime(tick);
}

//获取剩余时间
uint64_t Drop::GetLeftTime(uint64_t tick)
{
	uint64_t inter = tick - m_nDropTime;
	int32_t surviveSec = SurviveSec();
	//掉落总时间
	int32_t dropTotalSec = surviveSec * 1000 + m_nInitProtect;
	if (inter >= (uint64_t)dropTotalSec)
	{
		return 0;
	}
	inter = (uint64_t)dropTotalSec - inter;
	return inter;
}
//是否是杀戮之石物品
bool Drop::IsKillStone()
{
	return ((int32_t)EItemSubType::EItemSubType_special_kill_stone == m_itemSubType);
}

bool Drop::IsCurseFall()
{
	return ((int32_t)EItemSubType::EItemSubType_special_remains_god == m_itemSubType);
}

bool Drop::IsCampFlag()
{
	return ((int32_t)EItemSubType::EItemSubType_special_light_camp_flag == m_itemSubType || (int32_t)EItemSubType::EItemSubType_special_dark_camp_flag == m_itemSubType);
}

//生存时间
int32_t Drop::SurviveSec()
{
	int32_t surviveSec = DROP_SURVIVE_TIME;
	if (IsCurseFall())			//神之遗骸 有效时间10分钟
	{
		surviveSec = DROP_GOD_STONE_SURVIVE_TIME;
	}
	else if (IsKillStone())		//杀戮之石 活动期间
	{
		surviveSec = DROP_KILL_STONE_SURVIVE_TIME;
	}
	else if (IsCampFlag())
	{
		surviveSec = DROP_CAMP_FLAG_SURVIVE_TIME;
	}
	return surviveSec;
}

//是否再保护时间内
bool Drop::IsDuringProtect(uint64_t tick)
{
	if (tick - m_nDropTime <= (DROP_PROTECT_TIME * 1000 + m_nInitProtect))
	{
		return true;
	}
	return false;
}

//获取掉落物品
CItemBase *Drop::GetDropItem()
{
	return m_pItem;
}
//获取掉落金币
uint32_t Drop::GetDropGold()
{
	return m_nGold;
}
//是否可以拾取
bool Drop::CanPickUp(uint64_t nCid)
{
	if (m_del) //待删除的掉落不允许拾取
	{ 
		return false;
	}
	uint64_t tick = g_GetGlobalServerTime()->Tick(); 
	uint64_t leftsec = GetLeftTime(tick);
	if (0 == leftsec)
	{
		return false;
	}
	//初始保护时间
	if (tick - m_nDropTime <= m_nInitProtect)
	{
		return false;
	}

	bool bCan = false;

	//特殊处理阵营旌旗掉落 add by zlb
	//阵营旌旗属于公会掉落 但又区别于公会掉落
	//1.阵营旌旗整个生命周期只能被参与活动的两个公会成员拾取
	//2.阵营旌旗不需要掉落保护时间
	if (IsCampFlag())
	{
		Player *pPlayer = m_pScene->GetPlayer(nCid);
		if (nullptr != pPlayer)
		{
			//判断是否属于工会
			SET_UINT64::iterator iter = m_setTypeVal.find((uint64_t)pPlayer->GetAttr(C_UNION_ID));
			if (iter != m_setTypeVal.end())
			{
				bCan = true;
			}
		}

		return bCan;
	}

	if ((int8_t)EDropType::EDropType_Independence == m_byDropType)
	{
		SET_UINT64::iterator iter = m_setTypeVal.find(nCid);
		if (iter != m_setTypeVal.end())
		{
			bCan = true;
		}
	}
	else if ((int8_t)EDropType::EDropType_Personal == m_byDropType)
	{
		//个人掉落和组队掉落有掉落保护时间
		SET_UINT64::iterator iter = m_setTypeVal.find(nCid);
		if (iter != m_setTypeVal.end())
		{
			bCan = true;
		}
		else if (!IsDuringProtect(tick))
		{
			bCan = true;
		}
	}
	else if ((int8_t)EDropType::EDropType_Team == m_byDropType)
	{
		//组队掉落，需要判断拾取对象是否是队伍的成员
		//同一个队伍的人都可以拾取
		Player *pPlayer = dynamic_cast<Player*>(m_pScene->GetPlayer(nCid));
		if (nullptr != pPlayer)
		{
			SET_UINT64::iterator iter = m_setTypeVal.find((uint64_t)pPlayer->GetAttr(C_TEAM_ID));
			if (iter != m_setTypeVal.end())
			{
				bCan = true;
			}			
		}
		if (!bCan)
		{
			if (!IsDuringProtect(tick))
			{
				//过了掉落时间保护时间，任何人都可以拾取
				bCan = true;
			}
		}
		
	}
	else if ((int8_t)EDropType::EDropType_Public == m_byDropType)
	{
		bCan = true;
	}
	else if ((int8_t)EDropType::EDropType_Union == m_byDropType)
	{
		Player *pPlayer = m_pScene->GetPlayer(nCid);
		if (nullptr != pPlayer)
		{
			//判断是否属于工会
			SET_UINT64::iterator iter = m_setTypeVal.find((uint64_t)pPlayer->GetAttr(C_UNION_ID));
			if (iter != m_setTypeVal.end())
			{
				bCan = true;
			}
		}
		if (!bCan)
		{
			if (!IsDuringProtect(tick))
			{
				//过了掉落时间保护时间，任何人都可以拾取
				bCan = true;
			}
		}
	}
	else if ((int8_t)EDropType::EDropType_Camp == m_byDropType)
	{
		Player *pPlayer = m_pScene->GetPlayer(nCid);
		if (nullptr != pPlayer)
		{
			SET_UINT64::iterator iter = m_setTypeVal.find((uint64_t)pPlayer->GetCampId());
			if (iter != m_setTypeVal.end())
			{
				//是否属于同一阵营
				bCan = true;
			}			
		}
		if (!bCan)
		{
			if (!IsDuringProtect(tick))
			{
				//过了掉落时间保护时间，任何人都可以拾取
				bCan = true;
			}
		}
	}

	return bCan;
}

//经拾取了
void Drop::Pick()
{
	m_del = true;
	m_delTick = g_GetGlobalServerTime()->Tick();
	if (nullptr != m_pItem)
	{
		g_GetItemMgr()->FreeItemObj(m_pItem);
		m_pItem = nullptr;
	}	
	m_nGold = 0;

	//离开场景
	if (LeaveScene())
	{
		g_GetTimerAxis()->KillTimer(ETimer_ID_Drop, this);
		//下一帧准备等待回收
		g_GetCreatureMgr()->WaitDestory((Creature*)this);
	}
}

//移除
bool Drop::Remove()
{
	if (m_del)
	{
		return false;
	}
	uint32_t stoneItemId = 0;
	if (nullptr != m_pItem)
	{
		stoneItemId = m_pItem->GetItemID();
	}
	//
	Pick();
	//特殊物品的移除事件
	if (IsKillStone() || IsCurseFall() || IsCampFlag())
	{
		//目前只有杀戮之石需要触发事件
		if (nullptr != m_pItem)
		{
			DropDestoryEvent eventParam;
			eventParam.itemId = stoneItemId;
			g_GetEvent()->FireExecute(EVENT_DROP_DESTORY, GetCid(), CreatureKind(), &eventParam, sizeof(eventParam));
		}
	}

	return true;
}

//是否在初始保护时间内
bool Drop::IsDuringInitProtect(uint64_t tick)
{
	if (tick - m_nDropTime <= m_nInitProtect)
	{
		return true;
	}
	return false;
}

//获取掉落来源
const SDropSourcePram &Drop::GetDropSource()
{
	return m_source;
}

//掉落更新
void Drop::DropUpdate(uint64_t tick)
{
	if (m_del)
	{
		return;
	}
	//先检查掉落生存时间
	uint64_t leftsec = GetLeftTime(tick);	
	if ( 0 == leftsec
		|| m_byDropType <= (int8_t)EDropType::EDropType_none
		|| m_byDropType >= (int8_t)EDropType::EDropType_limit
		)
	{
		//离开场景
		m_del = true;
		m_delTick = g_GetGlobalServerTime()->Tick();
		if (LeaveScene())
		{
			g_GetTimerAxis()->KillTimer(ETimer_ID_Drop, this);

			if (IsKillStone() || IsCurseFall() || IsCampFlag())
			{
				//目前只有杀戮之石需要触发事件
				if (nullptr != m_pItem)
				{
					DropDestoryEvent eventParam;
					eventParam.itemId = m_pItem->GetItemID();
					g_GetEvent()->FireExecute(EVENT_DROP_DESTORY, GetCid(), CreatureKind(), &eventParam, sizeof(eventParam));
				}
			}
			//下一帧准备等待回收
			g_GetCreatureMgr()->WaitDestory((Creature*)this);
		}
	}
	else
	{
		if (IsCampFlag())
		{
			//特殊处理阵营旌旗掉落 add by zlb
			//阵营旌旗属于公会掉落 但又区别于公会掉落
			//1.阵营旌旗整个生命周期只能被参与活动的两个公会成员拾取
			//2.阵营旌旗不需要掉落保护时间
			return;
		}

		if ( ((int8_t)EDropType::EDropType_Personal == m_byDropType)
			|| ((int8_t)EDropType::EDropType_Team == m_byDropType)
			|| ((int8_t)EDropType::EDropType_Union == m_byDropType)
			|| ((int8_t)EDropType::EDropType_Camp == m_byDropType)
			)
		{
			//个人掉落和组队掉落有 20秒掉落保护时间,保护时间到了之后，变成了了公共掉落
			if (!IsDuringProtect(tick))
			{
				m_byDropType = (int8_t)EDropType::EDropType_Public;
				m_setTypeVal.clear();
				//
				PackageDropTypeUpdateRsp updateRsp;
				updateRsp.set_drop_cid(m_Cid);
				updateRsp.set_drop_type(m_byDropType);
				BroadCastData(EMODULE_ID_PACKAGE, LOGIC_TO_CLIENT_DROP_TYPE_UPDATE, &updateRsp);
			}
		}
	}
}
